package club.justwill.single.Controller;

import club.justwill.single.Service.UserService;
import club.justwill.single.aspect.LoginRequired;
import club.justwill.single.assembler.UserAddressAssemble;
import club.justwill.single.assembler.UserAssemble;
import club.justwill.single.bean.*;
import club.justwill.single.helper.SmsHelper;
import club.justwill.single.impl.ToolsImpl;
import club.justwill.single.model.*;
import club.justwill.single.persistence.document.MobileAuthCode;
import club.justwill.single.persistence.document.UserAdvice;
import club.justwill.single.persistence.jpo.User;
import club.justwill.single.persistence.store.MobileAuthCodeStore;
import club.justwill.single.util.JsonResponseHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.WebApplicationContext;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by xiangnan on 15-12-23.
 */

@RestController
@Scope(WebApplicationContext.SCOPE_SESSION)
public class UserController extends BaseController {
    private static Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private SmsHelper smsHelper;

    @Autowired
    private UserService userService;

    @Autowired
    private UserAssemble userAssemble;

    @Autowired
    private MobileAuthCodeStore mobileAuthCodeStore;

    @Autowired
    private UserAddressAssemble userAddressAssemble;

    @RequestMapping(value = URL_USER_GET_BY_ID, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse getUserById(@PathVariable long userId) {
        JsonResponse obj = new JsonResponse();
        User user = userService.getUserById(obj, userId);
        obj.setData(userAssemble.assembleUser(user));
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_USERS, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse getUsers(@RequestBody SearchUsers searchUser) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        List<UserResp> users = userService.getUsers(obj, token,searchUser.getIndex(),searchUser.getSize());
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setData(users);
            obj.setSuccessful();
        }
        return obj;
    }

    @RequestMapping(value = URL_USER_AUTHCODE, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse senAuthCode(@PathVariable("phone") String phone) {
        JsonResponse obj = new JsonResponse();
        if(!ToolsImpl.isValidMobile(phone)) {
            obj.setFailed();
            JsonResponseHelper.addError(obj, CoreConstants.MOBILE_ERROR);
        } else {
            sessionState.setMobile(phone);
            String code = smsHelper.sendAuthCode(sessionState);
            MobileAuthCode mobileAuthCode = new MobileAuthCode();
            mobileAuthCode.setMobile(phone);
            mobileAuthCode.setAuthcode(sessionState.getAuthCode());
            mobileAuthCode.setExpiry(ToolsImpl.changeLongToDate(new Date().getTime()+30*60*1000));
            mobileAuthCodeStore.save(mobileAuthCode);
            if(code.equals(CoreConstants.SEND_AUTHCODE_SUCCESSFUL)) {
                obj.setSuccessful();
            } else {
                obj.setFailed();
                JsonResponseHelper.addError(obj, CoreConstants.NET_WORD_ERROR);
            }
        }
        return obj;
    }

    @RequestMapping(value = URL_USER_SIGNUP, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse signUp(@RequestBody UserSignUp signUp) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        if(signUp.getChannel() == ServiceChannel.PC) {
            token.generatePcToken(sessionState);
        } else if (signUp.getChannel() == ServiceChannel.ANDROID) {
            token.generateAndroidToken(sessionState);
        } else if (signUp.getChannel() == ServiceChannel.IOS) {
            token.generateIosToken(sessionState);
        } else {
            token.generateToken(sessionState);
        }
        userService.signUp(token, signUp, obj, sessionState);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_USER_SAVE_ALIPAY_NUMBER, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse saveAlipayNumber(@PathVariable String alipayNumber) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        token.generateToken(sessionState);

        userService.saveAlipayNumber(obj, token, alipayNumber);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @RequestMapping(value = URL_USER_EX_LOGIN, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse exLogIn(@RequestBody ExLogIn exLogIn) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        token.generateToken(sessionState);
        userService.exLogIn(token, exLogIn, obj, sessionState);
        if (JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;

    }



    @RequestMapping(value = URL_USER_LOGIN, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse authenticate(@RequestBody UserLogin userLogin, HttpServletRequest request) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        sessionState.setSessionId(request.getSession().getId());
        User user = userService.authenticate(token, sessionState, userLogin, obj);
        if(user != null && !JsonResponseHelper.isHasError(obj)) {
            sessionState.setUserId(user.getUserId());
            sessionState.setUserType(user.getType());
            sessionState.setUserName(user.getNickName());
        }
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setData(userAssemble.assembleUser(user));
            obj.setSuccessful();
        }
        return obj;
    }
    @RequestMapping(value = URL_USER_LINK_WEIXIN, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse linkWeiXin(@PathVariable("code") String code) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        userService.linkWeiXin(obj, token, code, sessionState.getUserId());
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }
    @RequestMapping(value = URL_USE_PASSWORD_RESET, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse resetPassword(@RequestBody UserChangePassword userChangePassword){
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        token.generateToken(sessionState);
        userService.resetPassword(token, userChangePassword ,obj, sessionState);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @RequestMapping(value = URL_USER_LOGOUT, produces = CoreConstants.MIME_JSON)
    public JsonResponse logout(HttpServletRequest request){
        JsonResponse obj = new JsonResponse();
        if(!ToolsImpl.isEmpty(request.getCookies())){
            for(Cookie cookie:request.getCookies()){
                if("userId".equals(cookie.getName())){
                    try{
                        long userId = Long.parseLong(cookie.getValue());
                        sessionState.setUserId(userId);
                    }catch(Exception ex){
                        logger.info("cast exception userId");
                    }
                }
            }
            SecurityToken token = new SecurityToken(sessionState.getUserId());
            userService.logout(obj,token);
        }
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_GET_ADDRESS, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse getAddress() {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        token.generateToken(sessionState);
        List userAddress = userService.getAddress(token, obj);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
            obj.setData(userAddressAssemble.assembleAddressList(userAddress));
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_ADD_ADDRESS, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse addAddress(@RequestBody AddUserAddress addUserAddress) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        userService.addAddress(token, obj, addUserAddress);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_UPDATE_ADDRESS, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse updateAddress(@RequestBody UpdateUserAddress updateUserAddress) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        userService.updateAddress(token, obj, updateUserAddress);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_DELETE_ADDRESS, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse deleteAddress(@PathVariable String addressId) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        userService.deleteAddress(token, obj, addressId);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_USER_PROJECT_FOLLOW, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse followProject(@PathVariable long projectId) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        userService.followProject(token, obj, projectId);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_USER_PROJECT_UNFOLLOW, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse unFollowProject(@PathVariable long projectId) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        userService.unFollowProject(token, obj, projectId);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_USER_FOLLOWED_PROJECT_SEARCH, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse searchFollowedProject(SearchProjects searchProjects) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        List<ProjectsResp> followedProjectList;
        try {
            followedProjectList = userService.searchFollowedProject(token, obj, searchProjects);
        } catch (TransactionSystemException e) {
            followedProjectList = new ArrayList<ProjectsResp>();
        }

        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setData(followedProjectList);
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_USER_SUPPORTED_PROJECT_SEARCH, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse searchSupportedProject(SearchProjects searchProjects) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        List<ProjectsResp> supportedProjectList = userService.searchSupportedProject(token, obj, searchProjects);
        if (JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setData(supportedProjectList);
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_USER_SEARCH, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse searchCommercial(@PathVariable int index,@PathVariable int size) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        List<User> users = userService.searchCommercial(token, obj, index,size);
        if(JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }

    @LoginRequired
    @RequestMapping(value = URL_USER_SET_SECURITY_CODE, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse setSecurityCode(@RequestBody SecurityCode securityCode) {
        JsonResponse obj = new JsonResponse();
        SecurityToken token = new SecurityToken(sessionState.getUserId());
        token.generateToken(sessionState);
        userService.setSecurityCode(token, obj, securityCode);
        if (JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }
    @LoginRequired
    @RequestMapping(value = URL_USER_COLLET_ADVICE, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse collectAdvice(@RequestBody CollectAdvice collectAdvice) {
        JsonResponse obj = new JsonResponse();
        userService.collectAdvice(obj, sessionState.getUserId(), collectAdvice);
        if (JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setSuccessful();
        }
        return obj;
    }
    @RequestMapping(value = URL_USER_SEARCH_ADVICE, method = RequestMethod.POST, produces = CoreConstants.MIME_JSON)
    public JsonResponse searchAdvice(@RequestBody SearchAdvice searchAdvice) {
        JsonResponse obj = new JsonResponse();
        List<UserAdviceResp>  userAdviceRespList = userService.searchAdvice(obj, searchAdvice.getIndex(), searchAdvice.getSize());
        if (JsonResponseHelper.isHasError(obj)) {
            obj.setFailed();
        } else {
            obj.setData(userAdviceRespList);
            obj.setSuccessful();
        }
        return obj;
    }

    @RequestMapping(value = "/user/test", produces = CoreConstants.MIME_JSON)
    public JsonResponse test(HttpSession httpSession){
        JsonResponse obj = new JsonResponse();
        obj.setSuccessful();
        return obj;
    }
}
